package gui;

import conn.SocketManager;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.IOException;

import javax.swing.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;

/**
 * Interfaccia grafica del client.
 *
 * @author Claudio "Dna" Bonesana
 */
public class ClientWindow extends JFrame{

	private static final long serialVersionUID = 1L;

    private JMenuBar menuBar;

    private JMenu menuFile;
    private JMenuItem fileConnect;
    private JMenuItem fileDisconnect;
    private JMenuItem fileExit;

    private JMenu menuEdit;
    private JMenuItem editClear;

    private BorderLayout layout;

	private JButton send;
	private JTextPane textPane;
	private JTextField field;
	private JScrollPane scroll;

    private HTMLDocument doc;
    private HTMLEditorKit editorKit;

    private SocketManager socketManager;

    /**
     * Crea una nuova interfaccia grafica per il {@link SocketManager} associato.
     * @param socketManager un gestore di socket valido
     * @throws IOException
     */
	public ClientWindow(SocketManager socketManager) throws IOException{

        this.socketManager = socketManager;
		
		setTitle("My Little Client");
		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		setSize(new Dimension(320,480));

        menuBar = new JMenuBar();

        menuFile = new JMenu("File");
        menuFile.setMnemonic(KeyEvent.VK_F);

        fileConnect = new JMenuItem("Connect to server",KeyEvent.VK_C);
        fileConnect.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.ALT_MASK));
        fileConnect.getAccessibleContext().setAccessibleDescription("Connect to a server");
        fileConnect.addActionListener(new ConnectToServer());
        menuFile.add(fileConnect);

        fileDisconnect = new JMenuItem("Disconnect from server", KeyEvent.VK_D);
        fileDisconnect.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.ALT_MASK));
        fileDisconnect.getAccessibleContext().setAccessibleDescription("Disconnect from server");
        fileDisconnect.addActionListener(new DisconnectFromServer());
        fileDisconnect.setEnabled(false);
        menuFile.add(fileDisconnect);

        menuFile.addSeparator();

        fileExit = new JMenuItem("Exit");
        fileExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, InputEvent.ALT_MASK));
        fileExit.addActionListener(new ExitClient());
        menuFile.add(fileExit);

        menuEdit = new JMenu("Edit");
        menuEdit.setMnemonic(KeyEvent.VK_E);

        editClear = new JMenuItem("Clear console", KeyEvent.VK_C);
        editClear.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK));
        editClear.getAccessibleContext().setAccessibleDescription("Clear current console content");
        editClear.addActionListener(new ClearConsole());
        editClear.setEnabled(false);
        menuEdit.add(editClear);

        menuBar.add(menuFile);
        menuBar.add(menuEdit);

		layout = new BorderLayout();
		
		send = new JButton("Send");
        send.setEnabled(false);
        send.addActionListener(new SendValue());

		field = new JTextField();
        field.setEnabled(false);
        field.setEditable(true);
        field.addActionListener(new SendValue());

		textPane = new JTextPane();
        textPane.setContentType("text/html");
        textPane.setEditable(false);

        doc = (HTMLDocument)textPane.getStyledDocument();
        editorKit = (HTMLEditorKit)textPane.getEditorKit();

		scroll = new JScrollPane(textPane);

		getContentPane().setLayout(layout);
		getContentPane().add(scroll, BorderLayout.CENTER);
		getContentPane().add(field, BorderLayout.NORTH);
		getContentPane().add(send, BorderLayout.SOUTH);

        setJMenuBar(menuBar);

		setVisible(true);
	}

    /**
     * Aggiorna la chat con i nuovi messaggi.
     * @param str   il nuovo messaggio
     */
	public synchronized void update(String str){

        try {
            editorKit.insertHTML(doc,doc.getLength(),str,0,0,null);
            textPane.setCaretPosition(doc.getLength());
        } catch (BadLocationException ignored) {
        } catch (IOException ignored) {
        }
    }

    /**
     * Entra in modalità di comuniazione con il server.
     */
    public void enableWindow() {
        send.setEnabled(true);
        field.setEnabled(true);
        fileConnect.setEnabled(false);
        fileDisconnect.setEnabled(true);
        editClear.setEnabled(true);
    }

    /**
     * Esce dalla modalità di comunicazione con il server.
     */
    public void disableWindow() {
        send.setEnabled(false);
        field.setEnabled(false);
        fileConnect.setEnabled(true);
        fileDisconnect.setEnabled(false);
        editClear.setEnabled(false);
    }

    /**
     * Invia un nuovo messaggio al server attraverso il {@link SocketManager}.
     */
    private class SendValue implements ActionListener{
		public void actionPerformed(ActionEvent e) {
			String txt = field.getText();
			if (txt.equals("!q") || txt.equals("/exit")){
				socketManager.sendMessage("/exit");
			}
			field.setText("");
            socketManager.sendMessage(txt + "\n");
		}
	}

    /**
     * Apre una finestra di tipo {@link ClientConnect} per connettersi al server.
     */
    private class ConnectToServer implements ActionListener{

        @Override
        public void actionPerformed(ActionEvent e) {
            ClientConnect clientConnect = new ClientConnect(socketManager,menuBar);
            clientConnect.setVisible(true);
        }
    }

    /**
     * Disconnette dal server attuale.
     */
    private class DisconnectFromServer implements ActionListener{

        @Override
        public void actionPerformed(ActionEvent e) {
            socketManager.disconnect();
        }
    }

    /**
     * Esce dal client.
     */
    private class ExitClient implements ActionListener{

        @Override
        public void actionPerformed(ActionEvent e) {
            System.exit(0);
        }
    }

    /**
     * Pulisce la console dal testo contenuto.
     */
    private class ClearConsole implements ActionListener{

        @Override
        public void actionPerformed(ActionEvent e) {
            textPane.setText("");
        }
    }

}
